package de.iritgo.skillfull.entity;

import java.awt.Point;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;

import de.iritgo.skillfull.collision.MoveListener;
import de.iritgo.skillfull.component.Component;
import de.iritgo.skillfull.component.motion.PositionComponent;
import de.iritgo.skillfull.component.visitor.Visitor;
import de.iritgo.skillfull.config.ConfigManager;
import de.iritgo.skillfull.event.EventService;

public class EntityImpl implements Entity
{
	private List<Component> components;
	
	private List<Command> commands;

	private String id;
	
	private String name;

	private Command currentCommand;

	private Point position;
	
	private float rotation;

	private EventService eventService;
	
	private ConfigManager configManager;

	private boolean deactivate;
	
	public void setEventService(EventService eventService) 
	{
		this.eventService = eventService;
	}
	
	public void setConfigManager(ConfigManager configManager) 
	{
		this.configManager = configManager;
	}

	public void setComponents (List<Component> components)
	{
		this.components = components;
	}

	public List<Component> getComponents ()
	{
		return components;
	}

	public boolean hasComponent (String id)
	{
		if (id == null)
			return false;
		
		for (Component component : components)
		{
			if (component.getId ().equals (id))
				return true;
		}
		return false;
	}
	public Component getComponentById (String id)
	{
		if (id == null)
			return null;
		
		for (Component component : components)
		{
			if (component.getId ().equals (id))
				return component;
		}
		return null;
	}
	
	public void printAllEntityComponents ()
	{
		System.out.println (toString ());
		for (Component component : components)
		{
			System.out.println ("  " + component.getName () + ":" + component.getId ());
			component.printConfiguration ();
		}
	}
	public void init () 
	{
		deactivate = false;
		for (Component component : components)
		{
			component.init ();
		}
	}
	
	public String getId ()
	{
		return id;
	}

	public void setId (String id)
	{
		this.id = id;
	}

	public String getName ()
	{
		return name;
	}

	public void setName (String name)
	{
		this.name = name;
	}
	
	public Entity cloneEntity ()
	{
		// Spring Magic
		return null;
	}

	public void initialize ()
	{
		position = new Point (0, 0);
		
		for (Component component : components)
		{
			//Spring AOP error!
			component.setEntity (this);
		}
	}

	public void setPosition (int x, int y)
	{
		position.x = x;
		position.y = y;
	}

	public Point getPosition ()
	{
		return position;
	}
	
	public float getRotation() 
	{
		return rotation;
	}

	public void setRotation(float rotation) 
	{
		this.rotation = rotation;
	}

	@Override
	public void accept (Visitor visitor)
	{
		visitor.visit (this);
		
		for (Component component : components)
		{
			component.accept (visitor);
		}
	}

	@Override
	public void render (GameContainer container, Graphics g)
	{
		if (configManager.functionActive("showEntityCurrentCommand"))
		{
			g.drawString(getCurrentCommand () != null ? getCurrentCommand ().getName () + ":" + commands.size() : "IDLE", position.x, position.y+32);
		}
		
		for (Component component : components)
		{
			component.render (container, g, this);
		}
	}

	public void update (GameContainer container, int delta)
	{
		if (commands != null && commands.size () > 0)
		{
			Command command = commands.get (0);
			currentCommand = command;
			
			if (command.canPerform ())
				command.perform (delta);
			
			if (command.isDone ())
			{
				commands.remove (0);
				currentCommand = null;
			}
		}
		else
		{
			eventService.fireEvent(new EntityIdleEvent (this));
		}
		
		for (Component component : components)
		{
			component.update (container, delta, this);
		}
	}

	@Override
	public void removed() 
	{
		for (Component component : components)
		{
			component.removed (this);
		}
	}

	public void addCommand (Command command) 
	{
		if (commands == null)
		{
			commands = new LinkedList<Command> ();
		}
		if (command == null)
		{
			return;
		}
		commands.add (command);
	}
	
	public Command getCurrentCommand ()
	{
		return currentCommand;
	}

	public void cleanCommands () 
	{
		if (commands != null)
			commands.clear ();
	}

	@Override
	public void insertCommand(int index, Command command) 
	{
		commands.add(index, command);
	}

	@Override
	public void removeCommand(Command command) 
	{
		commands.remove (command);
	}
	
	public int getNumberOfCommands ()
	{
		if (commands == null)
		{
			return 0;
		}
		return commands.size();
	}
	
	public boolean isDeactivated ()
	{
		return deactivate;
	}
	
	public void deactivate ()  
	{
		this.deactivate = true;
		for (Component component : components)
		{
			component.deactivate ();
		}
	}
}
